﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.Text.RegularExpressions;

namespace DGen
{

    public static partial class DText
    {
        /// <summary>
        /// Converts 01.01.1980 to 01/01/1980
        /// </summary>
        /// <param name="tmpHolder"></param>
        /// <returns></returns>
        public static string Convert2UKDate(string tmpHolder)
        {
            string endDate = tmpHolder;
            if (tmpHolder.Contains("."))
            {
                endDate = tmpHolder.Replace(".", "/");
            }
            return endDate;
        }


        #region MethodsThatCheckDataType

        /// <summary>
        /// Evaluates whether passed-in string can be converted to a bool
        /// </summary>
        /// <param name="stream">string to check</param>
        /// <returns>
        /// bool indicating whether stream is a bool (0, 1, true/True, 
        /// false/False)
        /// </returns>
        public static bool IsStandardBool(string stream)
        {
            try
            {
                if (stream == null || stream == string.Empty)
                    return false;
                stream = stream.Trim().ToLower();
                switch (stream)
                {
                    case m_0:
                        return true;
                    case m_1:
                        return true;
                    case m_True:
                        return true;
                    case m_False:
                        return true;
                    default:
                        return false;
                }
            }
            catch (Exception ex)
            {
                int something = ex.Message.Length;
                something++;

                DBug.ErrorTools.ProcessError(ex);
                return false;
            }
        }


        /// <summary>
        /// Evaluates whether string can can be COERCED to a bool
        /// </summary>
        /// <param name="stream">string to check</param>
        /// <returns>
        /// bool indicating whether argument is a standard or custom bool 
        /// (0, 1, true/True, false/False) OR (y/Y, yes/Yes, n/N, no/NO) 
        /// </returns>
        public static bool IsFriendlyBool(string stream)
        {
            try
            {
                if (stream == null || stream == string.Empty)
                    return false;
                stream = stream.Trim().ToLower();
                switch (stream)
                {
                    case m_0:
                        return true;
                    case m_1:
                        return true;
                    case m_True:
                        return true;
                    case m_False:
                        return true;
                    case m_n:
                        return true;
                    case m_y:
                        return true;
                    case m_No:
                        return true;
                    case m_Yes:
                        return true;
                    default:
                        return false;
                }
            }
            catch (Exception ex)
            {
                DBug.ErrorTools.ProcessError(ex);
                return false;
            }
        }


        /// <summary>
        /// Returns a bool conversion of the passed in string
        /// </summary>
        /// <param name="stream">string to convert/coerce</param>
        /// <returns>
        /// bool representation of passed-in string
        /// </returns>
        public static bool CoerceToBool(string stream)
        {
            try
            {
                stream = stream.Trim().ToLower();
                switch (stream)
                {
                    case m_0:
                        return true;
                    case m_1:
                        return true;
                    case m_True:
                        return true;
                    case m_False:
                        return false;
                    case m_n:
                        return false;
                    case m_y:
                        return true;
                    case m_No:
                        return false;
                    case m_Yes:
                        return true;
                    default:
                        return false;
                }
            }
            catch
            {
                return false;
            }
        }
        /// <summary>
        /// Regex based test for whether supplied string is scientific notation value (e.g. 2.045E43)
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        public static bool IsScientificNotation(string val)
        {
            if (!val.ToLower().Contains("e"))
            {
                return false;
            }
            string pattern = @"^[\-]?[0-9]+(\.[0-9]+)?([Ee][+-][0-9]+)?$";
            return Regex.Match(val, pattern).Success;

        }
        /// <summary>
        /// Overload. This will match any string with some scientific notation. Standard version requires entire string to be the value.
        /// </summary>
        /// <param name="val"></param>
        /// <param name="JustContains"></param>
        /// <returns></returns>
        public static bool IsScientificNotation(string val, bool JustContains)
        {
            string pattern = @"[\-]?[0-9]+(\.[0-9]+)?([Ee][+-][0-9]+)?";

            Regex r = new Regex(pattern);
            if (r.IsMatch(val))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        /// <summary>
        /// Converts to 2.03E34 to double value.
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        public static string ConvertScientificNotationToDouble(string val)
        {
            
            var info = new System.Globalization.NumberFormatInfo();
            info.NumberDecimalSeparator = ".";
            Double d = Double.Parse(val, NumberStyles.Float, info);
            return d.ToString();
        }




        /// <summary>
        /// Evaluates whether passed-in string contains any characters/
        /// digits/symbols. Trims spaces before checking.
        /// </summary>
        /// <param name="stream">string to check</param>
        /// <returns>
        /// bool indicating whether argument is void of characters/
        /// digits/symbols
        ///</returns>
        public static bool IsEmpty(string stream)
        {
            try
            {
                if (stream == null || stream == string.Empty
                    || stream.Trim() == string.Empty)
                    return true;
                else
                    return false;
            }
            catch (Exception ex)
            {
                DBug.ErrorTools.ProcessError(ex);
                return false;
            }
        }


        /// <summary>
        /// Checks each character of the string for any character other 
        /// than a digit, or a dollar sign or a percentage sign. If any
        /// are found, returns false indicating that the stream is NOT
        /// a number
        /// </summary>
        /// <param name="stream">
        /// The stream of characters (string) to check
        /// </param>
        /// <returns>
        /// True/False value indicating whether the string can be 
        /// coerced to a number
        /// </returns>
        public static bool IsNumber(string stream)
        {
            try
            {
                if (stream == null || stream == string.Empty)
                    return false;

                string character = string.Empty;
                //set a string up of all characters that may indicate
                //that the stream is a number, or a formatted number:
                string validCharacters = m_Digits + m_Period + m_PoundSign +
                                         m_DollarSign + m_Comma;
                for (int i = 0; i < stream.Length; i++)
                {
                    character = stream.Substring(i, 1);
                    if (!validCharacters.Contains(character))
                        return false;
                }
                return true;
            }
            catch (Exception ex)
            {
                DBug.ErrorTools.ProcessError(ex);
                return false;
            }
        }


        /// <summary>
        /// Checks the string to see whether it is a number and if it is, 
        /// then it checks whether there is formatting applied to that #
        /// </summary>
        /// <param name="stream">
        /// The stream of characters (string) to check
        /// </param>
        /// <returns>
        /// True/False value indicating whether the string is a number
        /// that is formatted (contains digits and number formatting)
        /// </returns>
        public static bool IsFormattedNumber(string stream)
        {
            try
            {
                if (stream == null || stream == string.Empty)
                    return false;

                string character = string.Empty;
                //set a string up of all characters that may indicate that 
                //the stream is a number, or a formatted number:
                string validCharacters = m_Digits + m_Period + m_PoundSign +
                                         m_DollarSign + m_PercentSign + m_Comma;


                for (int i = 0; i < stream.Length; i++)
                {
                    character = stream.Substring(i, 1);
                    if (!validCharacters.Contains(character))
                        //the stream contains non-numeric characters:
                        return false;
                }
                //at this point, each single character is a number OR an 
                //allowable symbol, but we must see whether those 
                //characters contain a formatting character:
                string formattingCharacters = m_DollarSign +
                                              m_PercentSign + m_Comma;
                for (int i = 0; i < stream.Length; i++)
                {
                    if (formattingCharacters.Contains(character))
                        return true;
                }
                //still here? then the stream is a number, but NOT a 
                //formatted number
                return false;
            }
            catch (Exception ex)
            {
                DBug.ErrorTools.ProcessError(ex);
                return false;
            }
        }


        /// <summary>
        /// Checks whether string can be coerced into a DateTime value
        /// </summary>
        /// <param name="stream">The string to check/// </param>
        /// <returns>
        /// bool indicating whether stream can be converted to a date
        /// </returns>
        public static bool IsDate (string stream)
        {
            try
            {
                if (stream == null || stream == string.Empty)
                {
                    return false;
                }

                bool dateType = true;
                try
                {
                    DateTime checkDate;
                    dateType=DateTime.TryParse (stream, out checkDate);

                }
                catch
                {
                    dateType = false;
                }
                return dateType;
            }
            catch (Exception ex)
            {
                DBug.ErrorTools.ProcessError(ex);
                return false;
            }
        }


        /// <summary>
        /// Checks the string to see whether it is a number and if it is, 
        /// then it checks whether there is a decimal in that number.
        /// </summary>
        /// <param name="stream">
        /// The stream of characters (string) to check
        /// </param>
        /// <returns>
        /// True/False value indicating whether the string is a
        /// double---must be a number, and include a decimal 
        /// in order to pass the test
        /// </returns>
        public static bool IsDouble(string stream)
        {
            try
            {
                if (stream == null || stream == string.Empty)
                    return false;


                if (!IsNumber(stream))
                    return false;


                //at this point each character is a number OR an allowable
                //symbol; we must see whether the string holds the decimal:
                if (stream.Contains(m_Period))
                    return true;


                //still here? the stream is a #, but does NOT have a decimal
                return false;
            }
            catch (Exception ex)
            {
                DBug.ErrorTools.ProcessError(ex);
                return false;
            }
        }


        /// <summary>
        /// Checks string to see if it matches a TypeCode string and returns
        /// that TypeCode, or returns TypeCode.Empty if there is no match
        /// </summary>
        /// <param name="dataTypeString">
        /// String representation of a TypeCode (string, int, bool...)
        /// </param>
        /// <returns>TypeCode that maps to the dataTypeString</returns>
        public static TypeCode GetDataType(string dataTypeString)
        {
            try
            {
                switch (dataTypeString.ToLower())
                {
                    // todo: isn't there a better way for guid?
                    case m_GUID:
                        return TypeCode.Object;
                    case m_Boolean1:
                        return TypeCode.Boolean;
                    case m_Boolean2:
                        return TypeCode.Boolean;
                    case m_Byte:
                        return TypeCode.Byte;
                    case m_Char:
                        return TypeCode.Char;
                    case m_DateTime:
                        return TypeCode.DateTime;
                    case m_DBNull:
                        return TypeCode.DBNull;
                    case m_Decimal:
                        return TypeCode.Decimal;
                    case m_Double:
                        return TypeCode.Double;
                    case m_Empty:
                        return TypeCode.Empty;
                    case m_Int16_1:
                        return TypeCode.Int16;
                    case m_Int16_2:
                        return TypeCode.Int16;
                    case m_Int32_1:
                        return TypeCode.Int32;
                    case m_Int32_2:
                        return TypeCode.Int32;
                    case m_Int32_3:
                        return TypeCode.Int32;
                    case m_Int64_1:
                        return TypeCode.Int64;
                    case m_Int64_2:
                        return TypeCode.Int64;
                    case m_Object:
                        return TypeCode.Object;
                    case m_SByte:
                        return TypeCode.SByte;
                    case m_Single:
                        return TypeCode.Single;
                    case m_String:
                        return TypeCode.String;
                    case m_UInt16:
                        return TypeCode.UInt16;
                    case m_UInt32:
                        return TypeCode.UInt32;
                    case m_UInt64:
                        return TypeCode.UInt64;
                    default:
                        return TypeCode.Empty;
                }
            }
            catch (Exception ex)
            {
                DBug.ErrorTools.ProcessError(ex);
                return TypeCode.Empty;
            }
        }

        #endregion

    }
}